package cn.topcodes.tcsf.wechat.service;

import cn.topcode.unicorn.utils.EmojiUtil;
import cn.topcode.unicorn.utils.StringUtil;
import cn.topcode.unicorn.utils.UuidUtil;
import cn.topcode.unicorn.utils.http.HttpUtil;
import cn.topcode.unicorn.wxsdk.WXContext;
import cn.topcode.unicorn.wxsdk.base.UserInfo;
import cn.topcode.unicorn.wxsdk.base.WXResponseCode;
import cn.topcode.unicorn.wxsdk.user.dto.GetUserInfoResult;
import cn.topcode.unicorn.wxsdk.user.dto.GetUserListResult;
import cn.topcode.unicorn.wxsdk.user.dto.OpenIdList;
import cn.topcodes.tcsf.admin.commons.domain.Page;
import cn.topcodes.tcsf.admin.commons.domain.ValueRangeConstant;
import cn.topcodes.tcsf.admin.commons.generic.GenericService;
import cn.topcodes.tcsf.wechat.domain.entity.WechatMp;
import cn.topcodes.tcsf.wechat.domain.entity.WechatUser;
import cn.topcodes.tcsf.wechat.domain.entity.WechatUserBranch;
import cn.topcodes.tcsf.wechat.domain.vo.WechatUserVo;
import cn.topcodes.tcsf.wechat.mapper.WechatUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import tk.mybatis.mapper.entity.Example;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 微信用户 服务
 * @author unicorn
 * @date 2017-08-15 17:19:03
 */
@Service
public class WechatUserServiceImpl extends GenericService<WechatUser> implements WechatUserService {

    @Autowired
    private WechatMpService wechatMpService;

    @Autowired
    private WechatUserBranchService wechatUserBranchService;

    @Autowired
    private WechatFileService wechatFileService;

    @Autowired
    private WechatUserMapper wechatUserMapper;

    /**
     * 根据openId获取微信用户信息
     * @param openId
     * @return
     */
    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public WechatUser findByOpenId(String openId) {
        Assert.notNull(openId, "openId不能为空");
        WechatUserBranch userBranch = wechatUserBranchService.findByOpenId(openId);
        if (userBranch != null) {
            return this.findOne(userBranch.getUserId());
        }
        return null;
    }

    @Override
    public WechatUser findBy(Long wechatMpId, String openId) {
        Assert.notNull(wechatMpId, "wechatMpId不能为空");
        Assert.notNull(openId, "openId不能为空");
        WechatUserBranch userBranch = wechatUserBranchService.findBy(wechatMpId, openId);
        if (userBranch != null) {
            return this.findOne(userBranch.getUserId());
        }
        return null;
    }

    /**
     * 根据unionId获取微信用户信息
     * @param unionId
     * @return
     */
    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public WechatUser findByUnionId(String unionId) {
        Assert.notNull(unionId, "unionId不能为空");
        Example example = this.buildExample();
        example.or().andEqualTo(WechatUser.FIELD_UNION_ID, unionId);
        return this.findOne(example);
    }

    /**
     * APP用户使用微信登录
     * @param unionId
     * @param openId
     * @param type
     * @return
     */
    @Override
    @Transactional(readOnly = false)
    public WechatUser login(String accessToken, String unionId, String openId, String type) {
        Assert.notNull(unionId, "unionId不能为空");
        Assert.notNull(openId, "openId不能为空");

        WechatUser user = this.findByUnionId(unionId);
        WechatUserBranch userBranch = wechatUserBranchService.findByOpenId(openId);
        if (user == null) {
            UserInfo userInfo = WXContext.getUserInfo(accessToken, openId);
            user = new WechatUser();
            user.setUnionId(unionId);
            user.setOpenId(openId);
            user.setSubscribe(WechatUser.SUBSCRIBE_FALSE);
            user.setGender(userInfo.getSex() == 1 ? "Male" : "Female");
            user.setHeadImgUrl(userInfo.getHeadImgUrl());
            user.setNickname(EmojiUtil.emojiChange(userInfo.getNickname()));
            user.setCity(userInfo.getCity());
            user.setProvince(userInfo.getProvince());
            user.setCountry(userInfo.getCountry());
            user.setSubscribeTime(new Date());
            this.create(user);
        }
        if (userBranch == null) {
            userBranch = new WechatUserBranch();
            userBranch.setUserId(user.getId());
            userBranch.setOpenId(openId);
            userBranch.setSubscribe(user.getSubscribe());
            userBranch.setSubscribeTime(user.getSubscribeTime());
            userBranch.setType(type);
            wechatUserBranchService.create(userBranch);
        }
        return user;
    }

    /**
     * 同步所有微信用户信息
     */
    @Override
    public void syncAllUserFromMp(String mpId) {
        List<String> openIds = getAllOpenIdFromMp(mpId,null);
        for(String openId : openIds) {
            saveWechatUserFromMp(mpId, openId);
        }
    }

    @Override
    public void syncAllUserFromMp() {
        this.syncAllUserFromMp(wechatMpService.getDefaultMpId());
    }

    /**
     * 获取此公众号的所有用户的openId
     * @param openId
     * @return
     */
    private List<String> getAllOpenIdFromMp(String mpId, String openId) {
        List<String> openIds = new ArrayList<String>();
        GetUserListResult result = WXContext.getUserInvoker().getUserList(mpId, openId);
        if(result != null && result.getErrcode() != null
                && WXResponseCode.CODE_0_SUCCESS == result.getErrcode()) {
            OpenIdList openIdList = result.getData();
            String nextOpenId = null;
            if(openIdList != null && openIdList.getOpenid() != null && !openIdList.getOpenid().isEmpty()) {
                openIds.addAll(openIdList.getOpenid());
                nextOpenId = openIdList.getOpenid().get(openIdList.getOpenid().size() - 1);
            }
            if(result.getCount() >= 10000 && StringUtil.isNotBlank(nextOpenId)) {
                openIds.addAll(getAllOpenIdFromMp(mpId, nextOpenId));
            }
        }
        return openIds;
    }

    /**
     * 从微信服务器获取用户信息并存入数据库
     * @param openId
     */
    @Override
    public WechatUser saveWechatUserFromMp(String mpId, String openId) {

        GetUserInfoResult result = WXContext.getUserInvoker().getUserInfo(mpId, openId, "");
        if (result != null && result.getErrcode() != null
                && WXResponseCode.CODE_0_SUCCESS == result.getErrcode()) {

            WechatUser wechatUser = this.findByOpenId(openId);
            WechatUserBranch wechatUserBranch = null;

            if(wechatUser == null) {
                wechatUser = new WechatUser();
                wechatUserBranch = new WechatUserBranch();
                WechatMp wechatMp = this.wechatMpService.findWechatMpByMpId(mpId);
                wechatUserBranch.setWechatMpId(wechatMp.getId());
            }else {
                wechatUserBranch = this.wechatUserBranchService.findByOpenId(openId);
            }

            wechatUser.setUnionId(result.getUnionid());

            switch (result.getSex()) {
                case 1:
                    wechatUser.setGender(ValueRangeConstant.Gender.GENDER_MALE);
                    break;
                case 2:
                    wechatUser.setGender(ValueRangeConstant.Gender.GENDER_FEMALE);
                    break;
                default:
                    wechatUser.setGender(ValueRangeConstant.Gender.GENDER_UNKNOWN);
                    break;
            }
            wechatUser.setGroupId(result.getGroupid());
            wechatUser.setHeadImgUrl(result.getHeadimgurl());
            wechatUser.setLanguage(result.getLanguage());
            wechatUser.setOpenId(result.getOpenId());
            if(!StringUtil.isBlank(result.getNickname())) {
                wechatUser.setNickname(EmojiUtil.emojiChange(result.getNickname()));
            }else {
                wechatUser.setNickname("无名");
            }
            wechatUser.setCountry(result.getCountry());
            wechatUser.setProvince(result.getProvince());
            wechatUser.setCity(result.getCity());
            wechatUser.setRemark(result.getRemark());
            wechatUser.setSubscribe(WechatUser.SUBSCRIBE_TRUE);
            wechatUser.setSubscribeTime(new Date(result.getSubscribeTime() * 1000));
//                    wechatUser.setTagidList(result.get); TODO
            this.save(wechatUser);

            wechatUserBranch.setOpenId(result.getOpenId());
            wechatUserBranch.setType(WechatUserBranch.TYPE_MP);
            wechatUserBranch.setSubscribe(WechatUserBranch.SUBSCRIBE_TRUE);
            wechatUserBranch.setSubscribeTime(new Date(result.getSubscribeTime() * 1000));
            wechatUserBranch.setUserId(wechatUser.getId());
            this.wechatUserBranchService.save(wechatUserBranch);

            return wechatUser;
        }else {
            throw new IllegalStateException("从微信服务器获取用户信息失败，errcode:"
                    + result.getErrcode() + ",msg:" + result.getErrmsg());
        }
    }

    @Override
    public WechatUser saveWechatUserFromMp(String openId) {
        return this.saveWechatUserFromMp(wechatMpService.getDefaultMpId(), openId);
    }

    @Override
    public Page<WechatUserVo> findPage(Long wechatMpId, String nickname, String openId, Integer page, Integer size) {
        if(StringUtil.isBlank(nickname)) {
            nickname = "%";
        }else {
            nickname = "%" + nickname + "%";
        }
        if(StringUtil.isBlank(openId)) {
            openId = "%";
        }else {
            openId = "%" + openId + "%";
        }
        List<WechatUserVo> list = this.wechatUserMapper.findPage(wechatMpId, nickname, openId, page, size);
        int total = this.wechatUserMapper.count();
        return new Page<>(list, total, page, size);
    }

}
